/*
 *   Copyright (c) 2010-2022, SIUFUNG
 */
package net.siufung.market.base.app.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.base.Strings;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.siufung.core.model.EnumsVo;
import net.siufung.core.model.enums.DeletedEnum;
import net.siufung.core.page.PagerResult;
import net.siufung.core.result.Result;
import net.siufung.core.result.ResultFail;
import net.siufung.core.result.ResultOk;
import net.siufung.core.utils.CopyUtil;
import net.siufung.market.base.app.controller.assembler.AppAssembler;
import net.siufung.market.base.app.controller.model.app.AppDto;
import net.siufung.market.base.app.controller.model.app.AppSaveDto;
import net.siufung.market.base.app.controller.model.app.AppUpdateDto;
import net.siufung.market.base.app.controller.model.app.AppPageDto;
import net.siufung.market.base.app.controller.model.app.AppVo;
import net.siufung.market.base.app.controller.regulation.AppRegulation;
import net.siufung.market.base.app.enums.AppTypes;
import net.siufung.market.base.app.enums.GrantTypes;
import net.siufung.market.base.app.mapper.IAppMapper;
import net.siufung.market.base.app.mapper.entity.App;
import net.siufung.market.base.app.service.IAppService;
import net.siufung.market.base.app.spi.ICheckMenuOccupySpi;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * 应用信息 前端控制器
 *
 * @author 陈建峰
 * @date 2023-01-12 16:24:13
 * @since v1.0.0
 */
@Api(tags = "应用信息")
@Slf4j
@AllArgsConstructor
@RestController
@RequestMapping("/sys/app")
public class AppController {

    private final IAppMapper appMapper;
    private final IAppService appService;
    private final ICheckMenuOccupySpi checkMenuOccupySpi;

    /**
     * 通过主键获取 应用信息
     * @param id 主键
     * @return Result<AppVo>
     * */
    @ApiOperation(value = "通过Id获取应用信息信息")
    @GetMapping(value = "/id/{id}")
    public Result<AppVo> getById(
            @PathVariable("id") Integer id) {
        return Result.ok(
            AppAssembler.from(appMapper.selectById(id)));
    }

    /**
     * 获取 应用信息列表
     * @param appDto 属性
     * @return Result<List<AppVo>>
     * */
    @ApiOperation(value = "获取应用信息列表")
    @PostMapping(value = "/list")
    public Result<List<AppVo>> list(
            @RequestBody AppDto appDto) {
        return Result.ok(
            AppAssembler.fromList(appMapper.selectList(Wrappers.query(appDto.to()))));
    }

    /**
     * 获取 应用信息分页
     * @param appPageDto 属性
     * @return 查询分页结果
     * */
    @ApiOperation(value = "获取应用信息分页")
    @PostMapping(value="/page")
    public Result<PagerResult<AppVo>> getPage(
            @RequestBody AppPageDto appPageDto) {
        appPageDto.validated();
        QueryWrapper<App> wrapper = new QueryWrapper<>();
        wrapper.lambda().like(!Strings.isNullOrEmpty(appPageDto.getAppName()) ,
                App::getAppName, appPageDto.getAppName());
        wrapper.lambda().like(!Strings.isNullOrEmpty(appPageDto.getAppCode()) ,
                App::getAppCode, appPageDto.getAppCode());
        wrapper.lambda().ne(App::isDefaultFlag, Boolean.TRUE);
        wrapper.lambda().orderByAsc(App::getCreatedAt);
        IPage<App> appPage = appMapper.selectPage(
                new Page<>(appPageDto.getPageNo(), appPageDto.getPageSize()), wrapper);
        PagerResult<AppVo> appVoPage = new PagerResult<>(
                appPage.getCurrent(), appPage.getSize(), appPage.getTotal());
        appVoPage.setRecords(
            AppAssembler.fromList(appPage.getRecords()));
        return Result.ok(appVoPage);
    }

    /**
     * 获取应用类型列表
     * @return Result<List<EnumsVo>>
     * */
    @ApiOperation(value = "获取应用类型列表")
    @GetMapping(value = "/getAppTypeList")
    public Result<List<EnumsVo>> getAppTypeList() {
        return Result.ok(AppTypes.getList());
    }

    /**
     * 获取授权类型列表
     * @return Result<List<EnumsVo>>
     * */
    @ApiOperation(value = "获取授权类型列表")
    @GetMapping(value = "/getGrantTypeList")
    public Result<List<EnumsVo>> getGrantTypeList() {
        return Result.ok(GrantTypes.getList());
    }

    /**
     * 通过主键删除 应用信息 对象
     * @param id 主键
     * @return 删除结果
     * */
    @ApiOperation(value = "删除应用信息对象")
    @PostMapping(value="/remove/{id}")
    public Result<Void> removeById(
        @PathVariable("id") Integer id) {
        AppRegulation.Remove appRemoveRegulation = new AppRegulation.Remove(checkMenuOccupySpi);
        appRemoveRegulation.isSatisfiedBy(id);
        if(appService.removeById(id)){
            return Result.ok(ResultOk.REMOVE);
        }
        return Result.fail(ResultFail.DATA_REMOVE_ERROR);
    }

    /**
     * 创建 应用信息
     * @param appSaveDto 对象属性
     * @return 创建结果
     * */
    @ApiOperation(value = "创建 应用信息")
    @PostMapping(value="/create")
    public Result<Void> create(
            @RequestBody AppSaveDto appSaveDto) {
        appSaveDto.validated();
        AppRegulation.Save appCreateRegulation = new AppRegulation.Save(appMapper);
        appCreateRegulation.isSatisfiedBy(appSaveDto);
        if(appService.save(appSaveDto.to())){
            return Result.ok(ResultOk.ADD);
        }
        return Result.fail(ResultFail.DATA_ADD_ERROR);
    }

    /**
     * 更新 应用信息
     * @param appUpdateDto 对象属性
     * @return Result<Void>
     * */
    @ApiOperation(value = "更新 应用信息 信息")
    @PostMapping(value="/update")
    public Result<Void> update(
            @RequestBody AppUpdateDto appUpdateDto) {
        appUpdateDto.validated();
        AppRegulation.Update appUpdateRegulation = new AppRegulation.Update(appMapper);
        appUpdateRegulation.isSatisfiedBy(appUpdateDto);
        App appOf = appService.getById(appUpdateDto.getId());
        CopyUtil.copyPropertiesIgnoreNull(appUpdateDto.to(), appOf);
        if(appService.updateById(appOf)){
            return Result.ok(ResultOk.UPDATE);
        }
        return Result.fail(ResultFail.DATA_UPDATE_ERROR);
    }

    /**
     * 更新 应用信息 状态
     * @param id 主键
     * @param deleted 数据状态
     * @return Result<Void>
     * */
    @ApiOperation(value = "更新 应用信息 状态")
    @PostMapping(value="/status/{id}/{deleted}")
    public Result<Void> updateStatusById(
            @PathVariable("id") Integer id,
            @PathVariable("deleted") boolean deleted) {
        AppRegulation.Status appStatusRegulation = new AppRegulation.Status(checkMenuOccupySpi);
        appStatusRegulation.isSatisfiedBy(id);
        if(appService.updateStatusById(id, DeletedEnum.get(deleted))){
            return Result.ok(ResultOk.STATUS);
        }
        return Result.fail(ResultFail.DATA_UPDATE_ERROR);
    }

}